/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.bean.chart;

import com.bean.chart.iterfaces.AbstractChart;
import com.bean.chart.iterfaces.DataObserver;
import java.awt.*;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.util.*;


/**
 *
 * @author sammael
 */
public class Chart extends AbstractChart implements Serializable {
    
    
    
    private PropertyChangeSupport propertySupport;
    
    
    public Chart() {
        super();
        propertySupport = new PropertyChangeSupport(this);
    
        this.setMinimumSize(new Dimension(400,200));
        this.setPreferredSize(new Dimension(400,200));
       /* if(this.chartMap.isEmpty()){
            
            this.addChartData("Wykres");
            this.addChartData("Wykres2");
            this.addChartData("Wykres3");
            this.addChartData("Wykres4");
            
            this.chartColorMap.put("Wykres", Color.BLUE);
            this.chartColorMap.put("Wykres2", Color.RED);
            this.chartColorMap.put("Wykres3", Color.ORANGE);
            this.chartColorMap.put("Wykres4", Color.GREEN);

            this.addChartDataPoint("Wykres", 16.0);
            this.addChartDataPoint("Wykres", 15.0);
            this.addChartDataPoint("Wykres", 20.0);
            this.addChartDataPoint("Wykres", 30.0);
            this.addChartDataPoint("Wykres", 25.0);

            this.addChartDataPoint("Wykres2", 80.0);
            this.addChartDataPoint("Wykres2", 25.0);
            this.addChartDataPoint("Wykres2", 43.0);
            this.addChartDataPoint("Wykres2", 35.23);
            this.addChartDataPoint("Wykres2", 5.15);
            
            this.addChartDataPoint("Wykres3", 10.0);
            this.addChartDataPoint("Wykres3", 11.11);
            this.addChartDataPoint("Wykres3", 72.23);
            this.addChartDataPoint("Wykres3", 20.0);
            this.addChartDataPoint("Wykres3", 23.67);

            this.addChartDataPoint("Wykres4", 61.0);
            this.addChartDataPoint("Wykres4", 31.25);
            this.addChartDataPoint("Wykres4", 79.25);
            this.addChartDataPoint("Wykres4", 11.23);
            this.addChartDataPoint("Wykres4", 18.15);
            
        }*/
         Random random = new Random();
        for(int i = 0; i < 3; i++){
            String name = "Wykres"+i;
            Color randomColor = Color.getHSBColor( random.nextFloat(), 1.0F, 1.0F );
            this.chartColorMap.put(name, randomColor);
            this.addChartData(name);
            for(int j = 0; j < 1000; j++){
                int d = random.nextInt(50);
                this.addChartDataPoint(name, (double)d);
            }
            
            
        } 
    }
    
    @Override
    public void paintComponent(Graphics g) {
        g.setColor(this.getBackgroundColor());
        g.fillRect(0,0,this.getSize().width,this.getSize().height);
        
        int w = this.getSize().width -2;
        int h = this.getSize().height -2;
        
        Graphics2D g2 = (Graphics2D) g;
        if(this.isGridVisible()){
            paintGrid(g, w, h);
        }
        if(this.isValueVisible()){
            paintValue(g, h);
        }
        if(this.isLineVisible()){
            paintLine(g2, w, h);
        }
        if(this.isDotVisible()){
            paintDot(g2, w, h);
        }

        
    }
    
    @Override
    protected void paintGrid(Graphics g, int w, int h) {
       g.setColor(this.getGridColor());
       
       int x = 0;
       int stepX = w/(this.getValuesCount()-1);
       
       if(this.isXVisible()){
        for(int i = 0; i <= this.getValuesCount(); ++i){
            x = (i*stepX)+1;
            g.drawLine(x, 1, x, h);
        }
       }
        
       if(this.isYVisible()){
        int stepY = h/(getMarksCount());
        int y;
        x  = (this.getValuesCount()*stepX)+1;
        for(int i = 0 ; i <= getMarksCount();++i){
            y = (i*stepY)+1;
            g.drawLine(1, y, x-1, y);
        }
       }
      
       
    }

    @Override
    protected void paintLine(Graphics2D g2, int w, int h) {

      Stroke s = new BasicStroke(this.getStrokeSize());
      g2.setStroke(s);
      
      int stepX = w/(this.getValuesCount()-1);
        
         Set set = this.chartMap.entrySet();
      
      Iterator i = set.iterator();
      
      while(i.hasNext()){
          Map.Entry me = (Map.Entry)i.next();
          Color color = this.chartColorMap.get(me.getKey());
          g2.setColor(color);
          int x = 0;
          LinkedList<Double> ls = (LinkedList<Double> ) me.getValue();
          for(int j = 0; j<ls.size(); j++){
              double y = ls.get(j);
              int next = j+1;
              int x1 = x+1;
              if(j == ls.size() - 1){
                  continue;
              }
              else{
              double y1 = ls.get(next);
              double scale = this.getMaxYValue() / y;
              double scale1 = this.getMaxYValue() / y1;
              g2.draw(new Line2D.Double(x*stepX , h - h / scale , x1*stepX, h - h / scale1 ));
              x++;
              }
             
          }
      }
    }

    @Override
    protected void paintDot(Graphics2D g2, int w, int h) {
        
      int size = this.getDotSize();
      
      int stepX = w/(this.getValuesCount()-1);
      
      Set set = this.chartMap.entrySet();
      
      Iterator i = set.iterator();
      
      while(i.hasNext()){
          Map.Entry me = (Map.Entry)i.next();
          Color color = this.chartColorMap.get(me.getKey());
          g2.setColor(color);
          int x = 0;
          LinkedList<Double> ls = (LinkedList<Double> ) me.getValue();
          Iterator j = ls.iterator();
          while(j.hasNext()){
              double y = (Double) j.next();
              double scale = this.getMaxYValue() / y;
              g2.fill(new Rectangle2D.Double(x*stepX - size/2, h - h / scale - size/2, size, size));
              x++;
          }
      }
    }
    @Override
    protected void paintValue(Graphics g, int h){
        g.setColor(this.getValueColor());
        int stepY = h/(getMarksCount());
        double value = this.getMaxYValue() / this.getMarksCount();
        int y;
        for(int i = 0 ; i <= getMarksCount();++i){
            y = (i*stepY)+1;
            double diff = this.getMaxYValue() - i * value;
            DecimalFormat df = new DecimalFormat("#.##");
            String sDiff = df.format(diff);
            if(i == 0);
            else
                g.drawString(sDiff, 5, y-5);
       }
        
    }

    @Override
    protected void propertyChange(String property, double oldval, double newVal) {
        propertySupport.firePropertyChange(property, oldval, newVal);
    }

    @Override
    protected void propertyChange(String property, boolean oldval, boolean newVal) {
        propertySupport.firePropertyChange(property, oldval, newVal);
    }

    @Override
    protected void propertyChange(String property, int oldval, int newVal) {
        propertySupport.firePropertyChange(property, oldval, newVal);
    }

    @Override
    protected void propertyChange(String property, Object oldval, Object newVal) {
        propertySupport.firePropertyChange(property, oldval, newVal);
    }

    @Override
    public Map<String, Color> getData() {
        return chartColorMap;
    }

}
